home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / perl5 / auto / RPC / XML / Server / process_request.al < prev    next >
Encoding:
Text File  |  2008-11-04  |  12.6 KB  |  315 lines

  1. # NOTE: Derived from blib/lib/RPC/XML/Server.pm.
  2. # Changes made here will be lost when autosplit is run again.
  3. # See AutoSplit.pm.
  4. package RPC::XML::Server;
  5.  
  6. #line 1354 "blib/lib/RPC/XML/Server.pm (autosplit into blib/lib/auto/RPC/XML/Server/process_request.al)"
  7. ###############################################################################
  8. #
  9. #   Sub Name:       process_request
  10. #
  11. #   Description:    This is provided for the case when we run as a subclass
  12. #                   of Net::Server.
  13. #
  14. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  15. #                   $self     in      ref       This class object
  16. #                   $conn     in      ref       If present, it's a connection
  17. #                                                 object from HTTP::Daemon
  18. #
  19. #   Returns:        void
  20. #
  21. ###############################################################################
  22. sub process_request
  23. {
  24.     my $self = shift;
  25.     my $conn = shift;
  26.  
  27.     my ($req, $reqxml, $resp, $respxml, $do_compress, $parser, $com_engine,
  28.         $length, $read, $buf, $resp_fh, $tmpfile,
  29.         $peeraddr, $peerhost, $peerport);
  30.  
  31.     my $me = ref($self) . '::process_request';
  32.     unless ($conn and ref($conn))
  33.     {
  34.         $conn = $self->{server}->{client};
  35.         bless $conn, 'HTTP::Daemon::ClientConn';
  36.         ${*$conn}{'httpd_daemon'} = $self;
  37.  
  38.         if ($IO::Socket::SSL::VERSION and
  39.             $RPC::XML::Server::IO_SOCKET_SSL_HACK_NEEDED)
  40.         {
  41.             no strict 'vars';
  42.             unshift @HTTP::Daemon::ClientConn::ISA, 'IO::Socket::SSL';
  43.             $RPC::XML::Server::IO_SOCKET_SSL_HACK_NEEDED = 0;
  44.         }
  45.     }
  46.  
  47.     # These will be attached to any and all request objects that are
  48.     # (successfully) read from $conn.
  49.     $peeraddr = $conn->peeraddr;
  50.     $peerport = $conn->peerport;
  51.     $peerhost = $conn->peerhost;
  52.     while ($req = $conn->get_request('headers only'))
  53.     {
  54.         if ($req->method eq 'HEAD')
  55.         {
  56.             # The HEAD method will be answered with our return headers,
  57.             # both as a means of self-identification and a verification
  58.             # of live-status. All the headers were pre-set in the cached
  59.             # HTTP::Response object. Also, we don't count this for stats.
  60.             $conn->send_response($self->response);
  61.         }
  62.         elsif ($req->method eq 'POST')
  63.         {
  64.             # Get a XML::Parser::ExpatNB object
  65.             $parser = $self->parser->parse();
  66.  
  67.             if (($req->content_encoding || '') =~ $self->compress_re)
  68.             {
  69.                 unless ($self->compress)
  70.                 {
  71.                     $conn->send_error(RC_BAD_REQUEST,
  72.                                       "$me: Compression not permitted in " .
  73.                                       'requests');
  74.                     next;
  75.                 }
  76.  
  77.                 $do_compress = 1;
  78.             }
  79.  
  80.             if (($req->content_encoding || '') =~ /chunked/i)
  81.             {
  82.                 # Technically speaking, we're not supposed to honor chunked
  83.                 # transfer-encoding...
  84.             }
  85.             else
  86.             {
  87.                 $length = $req->content_length;
  88.                 if ($do_compress)
  89.                 {
  90.                     # Spin up the compression engine
  91.                     unless ($com_engine = Compress::Zlib::inflateInit())
  92.                     {
  93.                         $conn->send_error(RC_INTERNAL_SERVER_ERROR,
  94.                                           "$me: Unable to initialize the " .
  95.                                           'Compress::Zlib engine');
  96.                         next;
  97.                     }
  98.                 }
  99.  
  100.                 $buf = '';
  101.                 while ($length > 0)
  102.                 {
  103.                     if ($buf = $conn->read_buffer)
  104.                     {
  105.                         # Anything that get_request read, but didn't use, was
  106.                         # left in the read buffer. The call to sysread() should
  107.                         # NOT be made until we've emptied this source, first.
  108.                         $read = length($buf);
  109.                         $conn->read_buffer(''); # Clear it, now that it's read
  110.                     }
  111.                     else
  112.                     {
  113.                         $read = sysread($conn, $buf,
  114.                                         ($length < 2048) ? $length : 2048);
  115.                         unless ($read)
  116.                         {
  117.                             # Convert this print to a logging-hook call.
  118.                             # Umm, when I have real logging hooks, I mean.
  119.                             # The point is, odds are very good that $conn is
  120.                             # dead to us now, and I don't want this package
  121.                             # taking over SIGPIPE as well as the ones it
  122.                             # already monopolizes.
  123.                             #print STDERR "Error: Connection Dropped\n";
  124.                             return undef;
  125.                         }
  126.                     }
  127.                     $length -= $read;
  128.                     if ($do_compress)
  129.                     {
  130.                         unless ($buf = $com_engine->inflate($buf))
  131.                         {
  132.                             $conn->send_error(RC_INTERNAL_SERVER_ERROR,
  133.                                               "$me: Error inflating " .
  134.                                               'compressed data');
  135.                             # This error also means that even if Keep-Alive
  136.                             # is set, we don't know how much of the stream
  137.                             # is corrupted.
  138.                             $conn->force_last_request;
  139.                             next;
  140.                         }
  141.                     }
  142.  
  143.                     eval { $parser->parse_more($buf); };
  144.                     if ($@)
  145.                     {
  146.                         $conn->send_error(RC_INTERNAL_SERVER_ERROR,
  147.                                           "$me: Parse error in (compressed) " .
  148.                                           "XML request (mid): $@");
  149.                         # Again, the stream is likely corrupted
  150.                         $conn->force_last_request;
  151.                         next;
  152.                     }
  153.                 }
  154.  
  155.                 eval { $reqxml = $parser->parse_done(); };
  156.                 if ($@)
  157.                 {
  158.                     $conn->send_error(RC_INTERNAL_SERVER_ERROR,
  159.                                       "$me: Parse error in (compressed) " .
  160.                                       "XML request (end): $@");
  161.                     next;
  162.                 }
  163.             }
  164.  
  165.             # Dispatch will always return a RPC::XML::response.
  166.             # RT29351: If there was an error from RPC::XML::Parser (such as
  167.             # a message that didn't conform to spec), then return it directly
  168.             # as a fault, don't have dispatch() try and handle it.
  169.             if (ref $reqxml)
  170.             {
  171.                 # Set localized keys on $self, based on the connection info
  172.                 local $self->{peeraddr} = $peeraddr;
  173.                 local $self->{peerhost} = $peerhost;
  174.                 local $self->{peerport} = $peerport;
  175.                 $respxml = $self->dispatch($reqxml);
  176.             }
  177.             else
  178.             {
  179.                 $respxml = RPC::XML::fault->new(RC_INTERNAL_SERVER_ERROR,
  180.                                                 $reqxml);
  181.                 $respxml = RPC::XML::response->new($respxml);
  182.             }
  183.  
  184.             # Clone the pre-fab response and set headers
  185.             $resp = $self->response->clone;
  186.             # Should we apply compression to the outgoing response?
  187.             $do_compress = 0; # In case it was set above for incoming data
  188.             if ($self->compress and
  189.                 ($respxml->length > $self->compress_thresh) and
  190.                 (($req->header('Accept-Encoding') || '') =~
  191.                  $self->compress_re))
  192.             {
  193.                 $do_compress = 1;
  194.                 $resp->header(Content_Encoding => $self->compress);
  195.             }
  196.             # Next step, determine the response disposition. If it is above the
  197.             # threshhold for a requested file cut-off, send it to a temp file
  198.             if ($self->message_file_thresh and
  199.                 $self->message_file_thresh < $respxml->length)
  200.             {
  201.                 require File::Spec;
  202.                 # Start by creating a temp-file
  203.                 $tmpfile = $self->message_temp_dir || File::Spec->tmpdir;
  204.                 $tmpfile = File::Spec->catfile($tmpfile,
  205.                                                __PACKAGE__ . $$ . time);
  206.                 $tmpfile =~ s/::/-/g;
  207.                 unless (open($resp_fh, "+> $tmpfile"))
  208.                 {
  209.                     $conn->send_error(RC_INTERNAL_SERVER_ERROR,
  210.                                       "$me: Error opening $tmpfile: $!");
  211.                     next;
  212.                 }
  213.                 unlink $tmpfile;
  214.                 # Make it auto-flush
  215.                 my $old_fh = select($resp_fh); $| = 1; select($old_fh);
  216.  
  217.                 # Now that we have it, spool the response to it. This is a
  218.                 # little hairy, since we still have to allow for compression.
  219.                 # And though the response could theoretically be HUGE, in
  220.                 # order to compress we have to write it to a second temp-file
  221.                 # first, so that we can compress it into the primary handle.
  222.                 if ($do_compress)
  223.                 {
  224.                     my $fh2;
  225.                     $tmpfile .= '-2';
  226.                     unless (open($fh2, "+> $tmpfile"))
  227.                     {
  228.                         $conn->send_error(RC_INTERNAL_SERVER_ERROR,
  229.                                           "$me: Error opening $tmpfile: $!");
  230.                         next;
  231.                     }
  232.                     unlink $tmpfile;
  233.                     # Make it auto-flush
  234.                     $old_fh = select($fh2); $| = 1; select($old_fh);
  235.  
  236.                     # Write the request to the second FH
  237.                     $respxml->serialize($fh2);
  238.                     seek($fh2, 0, 0);
  239.  
  240.                     # Spin up the compression engine
  241.                     unless ($com_engine = Compress::Zlib::deflateInit())
  242.                     {
  243.                         $conn->send_error(RC_INTERNAL_SERVER_ERROR,
  244.                                           "$me: Unable to initialize the " .
  245.                                           'Compress::Zlib engine');
  246.                         next;
  247.                     }
  248.  
  249.                     # Spool from the second FH through the compression engine,
  250.                     # into the intended FH.
  251.                     $buf = '';
  252.                     my $out;
  253.                     while (read($fh2, $buf, 4096))
  254.                     {
  255.                         unless (defined($out = $com_engine->deflate(\$buf)))
  256.                         {
  257.                             $conn->send_error(RC_INTERNAL_SERVER_ERROR,
  258.                                               "$me: Compression failure in " .
  259.                                               'deflate()');
  260.                             next;
  261.                         }
  262.                         print $resp_fh $out;
  263.                     }
  264.                     # Make sure we have all that's left
  265.                     unless (defined($out = $com_engine->flush))
  266.                     {
  267.                         $conn->send_error(RC_INTERNAL_SERVER_ERROR,
  268.                                           "$me: Compression flush failure in" .
  269.                                           ' deflate()');
  270.                         next;
  271.                     }
  272.                     print $resp_fh $out;
  273.  
  274.                     # Close the secondary FH. Rewinding the primary is done
  275.                     # later.
  276.                     close($fh2);
  277.                 }
  278.                 else
  279.                 {
  280.                     $respxml->serialize($resp_fh);
  281.                 }
  282.                 seek($resp_fh, 0, 0);
  283.  
  284.                 $resp->content_length(-s $resp_fh);
  285.                 $resp->content(sub {
  286.                                    my $b = '';
  287.                                    return undef unless
  288.                                        defined(read($resp_fh, $b, 4096));
  289.                                    $b;
  290.                                });
  291.             }
  292.             else
  293.             {
  294.                 # Treat the content strictly in-memory
  295.                 $buf = $respxml->as_string;
  296.                 $buf = Compress::Zlib::compress($buf) if $do_compress;
  297.                 $resp->content($buf);
  298.                 $resp->content_length($respxml->length);
  299.             }
  300.  
  301.             $conn->send_response($resp);
  302.             undef $resp;
  303.         }
  304.         else
  305.         {
  306.             $conn->send_error(RC_FORBIDDEN);
  307.         }
  308.     }
  309.  
  310.     return;
  311. }
  312.  
  313. # end of RPC::XML::Server::process_request
  314. 1;
  315.